home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / nevow / stan.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-03-23  |  27KB  |  673 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''An s-expression-like syntax for expressing xml in pure python.
  5.  
  6. Stan tags allow you to build XML documents using Python. Stan tags
  7. have special attributes that enable the developer to insert hooks in
  8. the document for locating data and custom rendering.
  9.  
  10. Stan is a DOM, or Document Object Model, implemented using
  11. basic Python types and functions called "flatteners". A flattener is
  12. a function that knows how to turn an object of a specific type
  13. into something that is closer to an HTML string. Stan differs
  14. from the W3C DOM by not being as cumbersome and heavy
  15. weight. Since the object model is built using simple python types
  16. such as lists, strings, and dictionaries, the API is simpler and
  17. constructing a DOM less cumbersome.
  18.  
  19. Stan also makes it convenient to build trees of XML in pure python
  20. code. See nevow.stan.Tag for details, and nevow.tags for tag
  21. prototypes for all of the XHTML element types.
  22. '''
  23. from __future__ import generators
  24. from zope.interface import implements
  25. from nevow import inevow
  26.  
  27. class Proto(str):
  28.     '''Proto is a string subclass. Instances of Proto, which are constructed
  29.     with a string, will construct Tag instances in response to __call__
  30.     and __getitem__, delegating responsibility to the tag.
  31.     '''
  32.     __slots__ = []
  33.     
  34.     def __call__(self, **kw):
  35.         return Tag(self)(**kw)
  36.  
  37.     
  38.     def __getitem__(self, children):
  39.         return Tag(self)[children]
  40.  
  41.     
  42.     def fillSlots(self, slotName, slotValue):
  43.         return Tag(self).fillSlots(slotName, slotValue)
  44.  
  45.     
  46.     def clone(self, deep = True):
  47.         return self
  48.  
  49.  
  50.  
  51. class xml(object):
  52.     '''XML content marker.
  53.  
  54.     xml contains content that is already correct XML and should not be escaped
  55.     to make it XML-safe. xml can contain unicode content and will be encoded to
  56.     utf-8 when flattened.
  57.     '''
  58.     __slots__ = [
  59.         'content']
  60.     
  61.     def __init__(self, content):
  62.         self.content = content
  63.  
  64.     
  65.     def __repr__(self):
  66.         return '<xml %r>' % self.content
  67.  
  68.  
  69.  
  70. class raw(str):
  71.     """Raw content marker.
  72.  
  73.     Raw content is never altered in any way. It is a sequence of bytes that will
  74.     be passed through unchanged to the XML output.
  75.  
  76.     You probably don't want this - look at xml first.
  77.     """
  78.     __slots__ = []
  79.  
  80.  
  81. def cdata(data):
  82.     '''CDATA section. data must be a string
  83.     '''
  84.     return xml('<![CDATA[%s]]>' % data)
  85.  
  86.  
  87. class directive(object):
  88.     '''Marker for a directive in a template
  89.     '''
  90.     __slots__ = [
  91.         'name']
  92.     
  93.     def __init__(self, name):
  94.         self.name = name
  95.  
  96.     
  97.     def __repr__(self):
  98.         return "directive('%s')" % self.name
  99.  
  100.     
  101.     def __hash__(self):
  102.         return hash((directive, self.name))
  103.  
  104.     
  105.     def __cmp__(self, other):
  106.         if isinstance(other, directive):
  107.             return cmp(self.name, other.name)
  108.         return NotImplemented
  109.  
  110.  
  111.  
  112. class slot(object):
  113.     '''Marker for slot insertion in a template
  114.     '''
  115.     __slots__ = [
  116.         'name',
  117.         'children',
  118.         'default']
  119.     
  120.     def __init__(self, name, default = None):
  121.         self.name = name
  122.         self.children = []
  123.         self.default = default
  124.  
  125.     
  126.     def __repr__(self):
  127.         return "slot('%s')" % self.name
  128.  
  129.     
  130.     def __getitem__(self, children):
  131.         '''Allow slots to have children. These children will not show up in the
  132.         output, but they will be searched for patterns.
  133.         '''
  134.         if not isinstance(children, (list, tuple)):
  135.             children = [
  136.                 children]
  137.         
  138.         self.children.extend(children)
  139.         return self
  140.  
  141.     
  142.     def __iter__(self):
  143.         """Prevent an infinite loop if someone tries to do
  144.             for x in slot('foo'):
  145.         """
  146.         raise NotImplementedError, 'Stan slot instances are not iterable.'
  147.  
  148.  
  149.  
  150. class _PrecompiledSlot(object):
  151.     '''
  152.     Marker for slot insertion into a template which has been precompiled.
  153.  
  154.     This differs from a normal slot in that it captures some attributes of its
  155.     context at precompilation time so that it can be rendered properly (as
  156.     these attributes are typically lost during precompilation).
  157.     '''
  158.     __slots__ = [
  159.         'name',
  160.         'children',
  161.         'default',
  162.         'isAttrib',
  163.         'inURL',
  164.         'inJS',
  165.         'inJSSingleQuoteString']
  166.     
  167.     def __init__(self, name, children, default, isAttrib, inURL, inJS, inJSSingleQuoteString):
  168.         self.name = name
  169.         self.children = children
  170.         self.default = default
  171.         self.isAttrib = isAttrib
  172.         self.inURL = inURL
  173.         self.inJS = inJS
  174.         self.inJSSingleQuoteString = inJSSingleQuoteString
  175.  
  176.     
  177.     def __repr__(self):
  178.         return '_PrecompiledSlot(%r, isAttrib=%r, inURL=%r, inJS=%r, inJSSingleQuoteString=%r)' % (self.name, self.isAttrib, self.inURL, self.inJS, self.inJSSingleQuoteString)
  179.  
  180.  
  181.  
  182. class Tag(object):
  183.     """Tag instances represent XML tags with a tag name, attributes,
  184.     and children. Tag instances can be constructed using the Prototype
  185.     tags in the 'tags' module, or may be constructed directly with a tag
  186.     name. Tags have two special methods, __call__ and __getitem__,
  187.     which make representing trees of XML natural using pure python
  188.     syntax. See the docstrings for these methods for more details.
  189.     """
  190.     implements(inevow.IQ)
  191.     specials = [
  192.         'data',
  193.         'render',
  194.         'remember',
  195.         'pattern',
  196.         'key',
  197.         'macro']
  198.     slotData = None
  199.     
  200.     def __init__(self, tag, attributes = None, children = None, specials = None):
  201.         self.tagName = tag
  202.         if attributes is None:
  203.             self.attributes = { }
  204.         else:
  205.             self.attributes = attributes
  206.         if children is None:
  207.             self.children = []
  208.         else:
  209.             self.children = children
  210.         if specials is None:
  211.             self._specials = { }
  212.         else:
  213.             self._specials = specials
  214.  
  215.     
  216.     def fillSlots(self, slotName, slotValue):
  217.         """Remember the stan 'slotValue' with the name 'slotName' at this position
  218.         in the DOM. During the rendering of children of this node, slots with
  219.         the name 'slotName' will render themselves as 'slotValue'.
  220.         """
  221.         if self.slotData is None:
  222.             self.slotData = { }
  223.         
  224.         self.slotData[slotName] = slotValue
  225.         return self
  226.  
  227.     
  228.     def patternGenerator(self, pattern, default = None):
  229.         """Returns a psudeo-Tag which will generate clones of matching
  230.         pattern tags forever, looping around to the beginning when running
  231.         out of unique matches.
  232.  
  233.         If no matches are found, and default is None, raise an exception,
  234.         otherwise, generate clones of default forever.
  235.  
  236.         You can use the normal stan syntax on the return value.
  237.  
  238.         Useful to find repeating pattern elements. Example rendering function:
  239.  
  240.         >>> def simpleSequence(context, data):
  241.         ...   pattern = context.patternCloner('item')
  242.         ...   return [pattern(data=element) for element in data]
  243.         """
  244.         patterner = _locatePatterns(self, pattern, default)
  245.         return PatternTag(patterner)
  246.  
  247.     
  248.     def allPatterns(self, pattern):
  249.         """Return a list of all matching pattern tags, cloned.
  250.  
  251.         Useful if you just want to insert them in the output in one
  252.         place.
  253.  
  254.         E.g. the sequence renderer's header and footer are found with this.
  255.         """
  256.         return [ tag.clone(deep = False, clearPattern = True) for tag in specialMatches(self, 'pattern', pattern) ]
  257.  
  258.     
  259.     def onePattern(self, pattern):
  260.         '''
  261.         Return a single matching pattern, cloned.
  262.  
  263.         If there is more than one matching pattern or no matching patterns,
  264.         raise an exception.
  265.  
  266.         Useful in the case where you want to locate one and only one sub-tag
  267.         and do something with it.
  268.         '''
  269.         data = getattr(self, 'pattern', Unset)
  270.         if data == pattern:
  271.             result = self
  272.         else:
  273.             result = _locateOne((pattern,), (lambda pattern: specialMatches(self, 'pattern', pattern)), 'pattern')
  274.         return result.clone(deep = False, clearPattern = True)
  275.  
  276.     
  277.     def __call__(self, **kw):
  278.         '''Change attributes of this tag. This is implemented using
  279.         __call__ because it then allows the natural syntax::
  280.  
  281.           table(width="100%", height="50%", border="1")
  282.  
  283.         Attributes may be \'invisible\' tag instances (so that
  284.         C{a(href=invisible(data="foo", render=myhrefrenderer))} works),
  285.         strings, functions, or any other object which has a registered
  286.         flattener.
  287.  
  288.         If the attribute is a python keyword, such as \'class\', you can
  289.         add an underscore to the name, like \'class_\'.
  290.  
  291.         A few magic attributes have values other than these, as they
  292.         are not serialized for output but rather have special purposes
  293.         of their own:
  294.  
  295.          - data: The value is saved on the context stack and passed to
  296.            render functions.
  297.  
  298.          - render: A function to call that may modify the tag in any
  299.            way desired.
  300.  
  301.          - remember: Remember the value on the context stack with
  302.            context.remember(value) for later lookup with
  303.            context.locate()
  304.  
  305.          - pattern: Value should be a key that can later be used to
  306.            locate this tag with context.patternGenerator() or
  307.            context.allPatterns()
  308.  
  309.          - key: A string used to give the node a unique label.  This
  310.            is automatically namespaced, so in C{span(key="foo")[span(key="bar")]}
  311.            the inner span actually has a key of \'foo.bar\'.  The key is
  312.            intended for use as e.g. an html \'id\' attribute, but will
  313.            is not automatically output.
  314.  
  315.          - macro - A function which will be called once in the lifetime
  316.            of the template, when the template is loaded. The return
  317.            result from this function will replace this Tag in the template.
  318.         '''
  319.         if not kw:
  320.             return self
  321.         for name in self.specials:
  322.             if kw.has_key(name):
  323.                 setattr(self, name, kw[name])
  324.                 del kw[name]
  325.                 continue
  326.             kw
  327.         
  328.         for k, v in kw.iteritems():
  329.             if k[-1] == '_':
  330.                 k = k[:-1]
  331.             elif k[0] == '_':
  332.                 k = k[1:]
  333.             
  334.             self.attributes[k] = v
  335.         
  336.         return self
  337.  
  338.     
  339.     def __getitem__(self, children):
  340.         '''Add children to this tag. Multiple children may be added by
  341.         passing a tuple or a list. Children may be other tag instances,
  342.         strings, functions, or any other object which has a registered
  343.         flatten.
  344.  
  345.         This is implemented using __getitem__ because it then allows
  346.         the natural syntax::
  347.  
  348.           html[
  349.               head[
  350.                   title["Hello World!"]
  351.               ],
  352.               body[
  353.                   "This is a page",
  354.                   h3["How are you!"],
  355.                   div(style="color: blue")["I hope you are fine."]
  356.               ]
  357.           ]
  358.         '''
  359.         if not isinstance(children, (list, tuple)):
  360.             children = [
  361.                 children]
  362.         
  363.         self.children.extend(children)
  364.         return self
  365.  
  366.     
  367.     def __iter__(self):
  368.         '''Prevent an infinite loop if someone tries to do
  369.             for x in stantaginstance:
  370.         '''
  371.         raise NotImplementedError, 'Stan tag instances are not iterable.'
  372.  
  373.     
  374.     def _clearSpecials(self):
  375.         '''Clears all the specials in this tag. For use by flatstan.
  376.         '''
  377.         self._specials = { }
  378.  
  379.     
  380.     def precompilable(self):
  381.         '''Is this tag precompilable?
  382.  
  383.         Tags are precompilable if they will not be modified by a user
  384.         render function.
  385.  
  386.         Currently, the following attributes prevent the tag from being
  387.         precompiled:
  388.  
  389.          - render (because the function can modify its own tag)
  390.          - pattern (because it is locatable and thus modifiable by an
  391.                     enclosing renderer)
  392.         '''
  393.         if self.render is Unset:
  394.             pass
  395.         return self.pattern is Unset
  396.  
  397.     
  398.     def _clone(self, obj, deep):
  399.         if hasattr(obj, 'clone'):
  400.             return obj.clone(deep)
  401.         if isinstance(obj, (list, tuple)):
  402.             return [ self._clone(x, deep) for x in obj ]
  403.         return obj
  404.  
  405.     
  406.     def clone(self, deep = True, clearPattern = False):
  407.         """Return a clone of this tag. If deep is True, clone all of this
  408.         tag's children. Otherwise, just shallow copy the children list
  409.         without copying the children themselves.
  410.         """
  411.         newattrs = self.attributes.copy()
  412.         for key in newattrs:
  413.             newattrs[key] = self._clone(newattrs[key], True)
  414.         
  415.         newslotdata = None
  416.         if self.slotData:
  417.             newslotdata = self.slotData.copy()
  418.             for key in newslotdata:
  419.                 newslotdata[key] = self._clone(newslotdata[key], True)
  420.             
  421.         
  422.         newtag = Tag(self.tagName, attributes = newattrs, children = newchildren, specials = self._specials.copy())
  423.         newtag.slotData = newslotdata
  424.         if clearPattern:
  425.             newtag.pattern = None
  426.         
  427.         return newtag
  428.  
  429.     
  430.     def clear(self):
  431.         '''Clear any existing children from this tag.
  432.         '''
  433.         self._specials = { }
  434.         self.children = []
  435.         return self
  436.  
  437.     
  438.     def __repr__(self):
  439.         rstr = ''
  440.         if self.attributes:
  441.             rstr += ', attributes=%r' % self.attributes
  442.         
  443.         if self._specials:
  444.             rstr += ', specials=%r' % self._specials
  445.         
  446.         if self.children:
  447.             rstr += ', children=%r' % self.children
  448.         
  449.         return 'Tag(%r%s)' % (self.tagName, rstr)
  450.  
  451.     
  452.     def freeze(self):
  453.         '''Freeze this tag so that making future calls to __call__ or __getitem__ on the
  454.         return value will result in clones of this tag.
  455.         '''
  456.         
  457.         def forever():
  458.             while True:
  459.                 yield self.clone()
  460.  
  461.         return PatternTag(forever())
  462.  
  463.  
  464.  
  465. class UnsetClass:
  466.     
  467.     def __nonzero__(self):
  468.         return False
  469.  
  470.     
  471.     def __repr__(self):
  472.         return 'Unset'
  473.  
  474.  
  475. Unset = UnsetClass()
  476.  
  477. def makeAccessors(special):
  478.     
  479.     def getSpecial(self):
  480.         return self._specials.get(special, Unset)
  481.  
  482.     
  483.     def setSpecial(self, data):
  484.         self._specials[special] = data
  485.  
  486.     return (getSpecial, setSpecial)
  487.  
  488. for name in Tag.specials:
  489.     setattr(Tag, name, property(*makeAccessors(name)))
  490.  
  491. del name
  492.  
  493. def visit(root, visitor):
  494.     '''
  495.     Invoke C{visitor} with each Tag in the stan DOM represented by C{root}.
  496.     '''
  497.     if isinstance(root, list):
  498.         for t in root:
  499.             visit(t, visitor)
  500.         
  501.     else:
  502.         visitor(root)
  503.         if isinstance(root, Tag):
  504.             for ch in root.children:
  505.                 visit(ch, visitor)
  506.             
  507.         
  508.  
  509.  
  510. class NodeNotFound(KeyError):
  511.     
  512.     def __str__(self):
  513.         return "The %s named %r wasn't found in the template." % tuple(self.args[:2])
  514.  
  515.  
  516.  
  517. class TooManyNodes(Exception):
  518.     
  519.     def __str__(self):
  520.         return 'More than one %r with the name %r was found.' % tuple(self.args[:2])
  521.  
  522.  
  523.  
  524. class PatternTag(object):
  525.     '''A pseudotag created by Tag.patternGenerator() which loops
  526.     through a sequence of matching patterns.'''
  527.     
  528.     def __init__(self, patterner):
  529.         self.pat = patterner.next()
  530.         self.patterner = patterner
  531.  
  532.     
  533.     def next(self):
  534.         if self.pat:
  535.             p = self.pat
  536.             self.pat = None
  537.             return p
  538.         return self.patterner.next()
  539.  
  540.  
  541.  
  542. def makeForwarder(name):
  543.     return (lambda self: getattr(self.next(), name)(*args, **kw))
  544.  
  545. for forward in [
  546.     '__call__',
  547.     '__getitem__',
  548.     'fillSlots']:
  549.     setattr(PatternTag, forward, makeForwarder(forward))
  550.  
  551.  
  552. def _locatePatterns(tag, pattern, default, loop = True):
  553.     gen = specialMatches(tag, 'pattern', pattern)
  554.     produced = []
  555.     for x in gen:
  556.         produced.append(x)
  557.         cloned = x.clone(deep = False, clearPattern = True)
  558.         yield cloned
  559.     
  560.     gen = None
  561.     if produced:
  562.         if not loop:
  563.             return None
  564.         while True:
  565.             for x in produced:
  566.                 cloned = x.clone(deep = False, clearPattern = True)
  567.                 yield cloned
  568.                 loop
  569.             
  570.     
  571.     if default is None:
  572.         raise NodeNotFound, ('pattern', pattern)
  573.     default is None
  574.     if hasattr(default, 'clone'):
  575.         while True:
  576.             yield default.clone(deep = False)
  577.     else:
  578.         while True:
  579.             yield default
  580.  
  581. Tag._locatePatterns = staticmethod(_locatePatterns)
  582.  
  583. def _locateOne(name, locator, descr):
  584.     found = False
  585.     for node in locator(name):
  586.         if found:
  587.             raise TooManyNodes(descr, name)
  588.         found
  589.         found = node
  590.     
  591.     if not found:
  592.         raise NodeNotFound(descr, name)
  593.     found
  594.     return found
  595.  
  596.  
  597. def specials(tag, special):
  598.     '''Generate tags with special attributes regardless of attribute value.
  599.     '''
  600.     for childOrContext in getattr(tag, 'children', []):
  601.         child = getattr(childOrContext, 'tag', childOrContext)
  602.         if getattr(child, special, Unset) is not Unset:
  603.             yield child
  604.             continue
  605.         for match in specials(child, special):
  606.             yield match
  607.         
  608.     
  609.  
  610.  
  611. def specialMatches(tag, special, pattern):
  612.     '''
  613.     Generate special attribute matches starting with the given tag; if a tag
  614.     has special, do not look any deeper below that tag, whether it matches
  615.     pattern or not. Returns an iterable.
  616.     '''
  617.     for childOrContext in getattr(tag, 'children', []):
  618.         child = getattr(childOrContext, 'tag', childOrContext)
  619.         data = getattr(child, special, Unset)
  620.         if data == pattern:
  621.             yield child
  622.             continue
  623.         if data is Unset:
  624.             for match in specialMatches(child, special, pattern):
  625.                 yield match
  626.             
  627.     
  628.  
  629.  
  630. class CommentProto(Proto):
  631.     __slots__ = []
  632.     
  633.     def __call__(self, **kw):
  634.         return Comment(self)(**kw)
  635.  
  636.     
  637.     def __getitem__(self, children):
  638.         return Comment(self)[children]
  639.  
  640.  
  641.  
  642. class Comment(Tag):
  643.     
  644.     def __call__(self, **kw):
  645.         raise NotImplementedError('comments are not callable')
  646.  
  647.  
  648. invisible = Proto('')
  649.  
  650. class Entity(object):
  651.     
  652.     def __init__(self, name, num, description):
  653.         self.name = name
  654.         self.num = num
  655.         self.description = description
  656.  
  657.     
  658.     def __repr__(self):
  659.         return 'Entity(%r, %r, %r)' % (self.name, self.num, self.description)
  660.  
  661.  
  662.  
  663. class inlineJS(object):
  664.     
  665.     def __init__(self, children):
  666.         self.children = children
  667.  
  668.     
  669.     def __repr__(self):
  670.         return 'inlineJS(%s)' % (self.children,)
  671.  
  672.  
  673.